Completed
Pull Request — master (#63)
by Pieter Epeüs
07:54
created

objects.js ➔ flat   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
1
import { Validator } from '@hckrnews/validator';
2
3
/**
4
 * Object helper
5
 *
6
 * @param {object} schema
7
 *
8
 * @return {class}
9
 */
10
module.exports = schema => {
11
    const validator = new Validator(schema);
0 ignored issues
show
Unused Code introduced by
The constant validator seems to be never used. Consider removing it.
Loading history...
12
    return class Obj {
13
        /**
14
         * Set the original and prefix.
15
         *
16
         * @param {object} original
17
         * @param {string} prefix
18
         */
19
        constructor(original, prefix) {
20
            this.original = original;
21
            this.prefix = prefix;
22
            this.flatObject = {};
23
            this.validate();
24
            this.parse();
25
        }
26
27
        validate() {
28
            if (!validator.validate(this.original)) {
0 ignored issues
show
Bug introduced by
The variable validator seems to be never declared. If this is a global, consider adding a /** global: validator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
29
                console.log({ errors: validator.errors });
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
30
                throw new Error('Invalid input');
31
            }
32
        }
33
34
        /**
35
         * flatten the object 1 level per time.
36
         */
37
        parse() {
38
            Object.entries(this.original).forEach(
39
                ([originalRowIndex, originalRow]) => {
40
                    let index = originalRowIndex;
41
42
                    if (this.prefix) {
43
                        index = [this.prefix, originalRowIndex].join('.');
44
                    }
45
46
                    if (typeof originalRow === 'object') {
47
                        const childRows = new Obj(originalRow, index).flat;
48
49
                        this.flatObject = Object.assign(
50
                            this.flatObject,
51
                            childRows
52
                        );
53
54
                        return;
55
                    }
56
57
                    this.flatObject[index] = originalRow;
58
                }
59
            );
60
        }
61
62
        /**
63
         * Get the flat object.
64
         *
65
         * @return {object}
66
         */
67
        get flat() {
68
            return this.flatObject;
69
        }
70
71
        /**
72
         * Get the object entries.
73
         *
74
         * @return {array}
75
         */
76
        entries() {
77
            return Object.entries(this.flatObject);
78
        }
79
80
        /**
81
         * Get the object keys.
82
         *
83
         * @return {array}
84
         */
85
        keys() {
86
            return Object.keys(this.flatObject);
87
        }
88
89
        /**
90
         * Get the object values.
91
         *
92
         * @return {array}
93
         */
94
        values() {
95
            return Object.values(this.flatObject);
96
        }
97
98
        /**
99
         * Get the object length.
100
         *
101
         * @return {number}
102
         */
103
        get length() {
104
            return Object.keys(this.flatObject).length;
105
        }
106
107
        /**
108
         * Get an item by key.
109
         *
110
         * @param {string} key
111
         * @param {object|null} defaultValue
112
         *
113
         * @return {object|null}
114
         */
115
        getByKey(key, defaultValue) {
116
            if (this.originalHas(key)) {
117
                return Object.getOwnPropertyDescriptor(this.original, key)
118
                    .value;
119
            }
120
121
            if (this.has(key)) {
122
                return this.flatObject[key];
123
            }
124
125
            if (this.includes(key)) {
126
                return this.entries()
127
                    .filter(([currentKey]) => currentKey.startsWith(key))
128
                    .reduce((accumulator, [currentKey, currentValue]) => {
129
                        const subKey = currentKey.substring(key.length + 1);
130
                        accumulator[subKey] = currentValue;
131
                        return accumulator;
132
                    }, {});
133
            }
134
135
            return defaultValue;
136
        }
137
138
        /**
139
         * Get keys of an item.
140
         *
141
         * @param {array} keys
142
         * @param {object|null} defaultValue
143
         *
144
         * @return {object|null}
145
         */
146
        getFlatKeys(keys, defaultValue) {
147
            const result = this.entries().filter(([currentKey]) =>
148
                keys.some(key => currentKey.startsWith(key))
149
            );
150
151
            if (result.length < 1) {
152
                return defaultValue;
153
            }
154
155
            return Object.fromEntries(result);
156
        }
157
158
        /**
159
         * Get keys of an item.
160
         *
161
         * @param {array} keys
162
         * @param {object|null} defaultValue
163
         *
164
         * @return {object|null}
165
         */
166
        getKeys(keys, defaultValue) {
167
            const result = keys.reduce((accumulator, currentKey) => {
168
                const key = currentKey.toString();
169
                const value = this.getByKey(key);
170
171
                if (value) {
172
                    accumulator[key] = value;
173
                }
174
175
                return accumulator;
176
            }, {});
177
178
            if (Object.keys(result).length < 1) {
179
                return defaultValue;
180
            }
181
182
            return result;
183
        }
184
185
        /**
186
         * Check if the original object has a key.
187
         *
188
         * @param {string} key
189
         *
190
         * @return {boolean}
191
         */
192
        originalHas(key) {
193
            return Object.prototype.hasOwnProperty.call(this.original, key);
194
        }
195
196
        /**
197
         * Check if the object has a key.
198
         *
199
         * @param {string} key
200
         *
201
         * @return {boolean}
202
         */
203
        has(key) {
204
            return Object.prototype.hasOwnProperty.call(this.flatObject, key);
205
        }
206
207
        /**
208
         * Check if the object has a key that includes.
209
         *
210
         * @param {string} key
211
         *
212
         * @return {boolean}
213
         */
214
        includes(key) {
215
            return this.keys().filter(item => item.startsWith(key)).length > 0;
216
        }
217
    };
218
};
219